/************************************************************
* @file   gkt_list.h
************************************************************/

#ifndef GKT_LIST_H
#define GKT_LIST_H

#include "gkt_compiler.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _gkt_list	gkt_list_s;
struct _gkt_list {
	gkt_list_s	*prev;
	gkt_list_s	*next;
};

#define GKT_LIST_DEFINE(name)	\
	gkt_list_s name = { &name, &name }

#define gkt_list_foreach(head, pos)	\
	gkt_list_s *__list_next_ptr__;	\
	for (pos = (head)->next; __list_next_ptr__ = pos->next, pos != (head); pos = __list_next_ptr__)

#define gkt_list_foreach_inverse(head, pos)	\
	gkt_list_s *__list_prev_ptr__;	\
	for (pos = (head)->prev; __list_prev_ptr__ = pos->prev, pos != (head); pos = __list_prev_ptr__)

#define gkt_list_object(list, type, name)	\
	(type *)((unsigned int)(list) - __MEMBER_OFFSET(type, name))

#define gkt_list_is_empty(list)	((list).next == &(list))
#define gkt_list_is_empty_ptr(list_ptr)	((list_ptr)->next == (list_ptr))

#define gkt_list_is_not_empty(list)	((list).next != &(list))
#define gkt_list_is_not_empty_ptr(list_ptr)	((list_ptr)->next != (list_ptr))

#define gkt_list_first(head)	(head).next
#define gkt_list_first_ptr(head_ptr)	(head_ptr)->next

#define gkt_list_last(head)	(head).prev
#define gkt_list_last_ptr(head_ptr)	(head_ptr)->prev

__STATIC_INLINE void gkt_list_init(gkt_list_s *list)
{
	list->prev = list;
	list->next = list;
}

__STATIC_INLINE void gkt_list_add(gkt_list_s *prev, 
			gkt_list_s *list, gkt_list_s *next)
{
	list->prev = prev;
	list->next = next;
	prev->next = list;
	next->prev = list;
}
__STATIC_INLINE void gkt_list_add_head(gkt_list_s *head, gkt_list_s *list)
{
	gkt_list_add(head, list, head->next);
}
__STATIC_INLINE void gkt_list_add_tail(gkt_list_s *head, gkt_list_s *list)
{
	gkt_list_add(head->prev, list, head);
}

__STATIC_INLINE void gkt_list_delete(gkt_list_s *list)
{
	list->prev->next = list->next;
	list->next->prev = list->prev;
}

__STATIC_INLINE void gkt_list_delete_safe(gkt_list_s *list)
{
	gkt_list_delete(list);
	gkt_list_init(list);
}

#ifdef __cplusplus
}
#endif

#endif	/* GKT_LIST_H */


